<template>
  <div class="main-container">
    <!-- 条件搜索 -->
    <Condition>
      <!-- 算法名称 -->
      <div class="condition-item condition-item-3">
        <span class="condition-label">模块名称</span>
        <el-input 
          class="condition-input" 
          v-model="conditionForm.name" 
          placeholder="请输入算法名称" 
          @keyup.enter.native="getList"
          @change="getList"
        />
      </div>
      <!-- 算法模块 -->
      <div class="condition-item condition-item-3">
        <span class="condition-label">模块类别</span>
        <el-cascader
          class="condition-input" 
          clearable 
          v-model="conditionForm.moduleLibSelect" 
          :options="moduleLibs"
          :props="{
            value: 'id',
            label: 'name',
            children: 'children',
            checkStrictly: true
          }" 
          @change="selectModuleLibs"
        />
      </div>
      <!-- 算法平台 -->
      <div class="condition-item condition-item-3">
        <span class="condition-label">算法平台</span>
        <el-select 
          class="condition-input" 
          v-model="conditionForm.system" 
          placeholder="请选择算法平台"
          clearable
          @change="getList"
        >
          <el-option v-for="(item, index) in systems" :key="index" :label="item.name" :value="item.id" />
        </el-select>
      </div>
      <!-- <div class="condition-item condition-item-5">
        <span class="condition-label">状态</span>
        <el-select 
          class="condition-input" 
          v-model="conditionForm.status" 
          placeholder="请选择算法状态"
          clearable
          @change="getList"
        >
          <el-option v-for="(item, index) in taskStatus" :key="index" :label="item.label" :value="item.value" />
        </el-select>
      </div> -->
    </Condition>
    <!-- 数据表格部分 -->
    <div class="data-show">
      <!-- 头部操作按钮部分 -->
      <div class="data-actions">
        <span class="aniTxtBtn action" @click="linkToCreate">新增模块</span>
      </div>
      <!-- 底下表格 -->
      <div class="data-table">
        <el-table border v-loading="conditionForm.loading" :data="datas" stripe show-header>
          <el-table-column label="序号" align="center" type="index" width="100" />
          <el-table-column label="名称" align="center" prop="name"  />
          <el-table-column label="负责人" align="center" prop="createBy" width="100" />
          <el-table-column label="算法平台" align="center" show-overflow-tooltip prop="system" width="100">
            <template #default="{ row }">
              {{ getShow(row.system, 'id', systems, 'name') }}
            </template>
          </el-table-column>
          <el-table-column label="模块类别" align="center" show-overflow-tooltip prop="moduleLibId">
            <template #default="{ row }">
              {{ getModuleLibName(row.moduleLibId) }}
            </template>
          </el-table-column>
          <el-table-column label="是否默认" align="center" show-overflow-tooltip prop="isDefault" width="100">
            <template #default="{ row }">
              {{ getShow(row.isDefault, 'value', defaults, 'label') }}
            </template>
          </el-table-column>
          <el-table-column label="描述" align="center" show-overflow-tooltip prop="description">
            <template #default="{row}">
              {{ row.description ? row.description : '--' }}
            </template>
          </el-table-column>
          <el-table-column label="创建时间" align="center" show-overflow-tooltip prop="createTime" />
          <el-table-column label="操作" align="center" width="300" fit>
            <template #default="{ row }">
              <transition :name="row.changeDownload ? 'links-out' : 'links-in'" mode="out-in">
                <div class="table-actions table-actions-column" v-if="!row.changeDownload">
                  <div class="actions-column">
                    <button :disabled="!row.linkFileId || (Array.isArray(row.linkFiles) && row.linkFiles.length < 1) || !row.linkFiles" class="aniTxtBtn main-color" @click="changeDownload(row, 1)">静态链接</button>
                    <button :disabled="!row.dynamicLinkFileId || (Array.isArray(row.dynamicLinkFiles) && row.dynamicLinkFiles.length < 1) || !row.dynamicLinkFiles" class="aniTxtBtn main-color" @click="changeDownload(row, 2)">动态链接</button>
                    <button :disabled="!row.sourceFileId || row.sourceFlag" class="aniTxtBtn main-color"  @click="download(row, 'sourceFileId', 'sourceFlag')">下载源码</button>
                  </div>
                  <div class="actions-column">
                    <button class="aniTxtBtn blue" @click="linkToEdit(row)">编辑</button>
                    <button class="aniTxtBtn red" @click="del(row)">删除</button>
                  </div>
                </div>
                <div class="links" v-else-if="row.changeDownload == 1">
                  <div class="links-top">
                    <span class="links-all" v-if="Array.isArray(row.linkFiles) && row.linkFiles.length > 1" @click="downloadlinks(row, 'linkFiles')">一键下载</span>
                    <span v-else>静态链接库下载</span>
                    <i class="iconfont icon-guanbi2 links-close" @click="changeDownload(row, 0)"></i>
                  </div>
                  <div class="links-container">
                    <div class="links-item" :class="{disabled: link.linkFlag}" v-for="(link, index) in row.linkFiles" :key="index" @click="linkDowload(link)">{{ link.fileName }}</div>
                  </div>
                </div>
                <div class="links" v-else-if="row.changeDownload == 2">
                  <div class="links-top">
                    <span class="links-all" v-if="Array.isArray(row.dynamicLinkFiles) && row.dynamicLinkFiles.length > 1" @click="downloadlinks(row, 'dynamicLinkFiles')">一键下载</span>
                    <span v-else>动态链接库下载</span>
                    <i class="iconfont icon-guanbi2 links-close" @click="changeDownload(row, 0)"></i>
                  </div>
                  <div class="links-container">
                    <div class="links-item" :class="{disabled: link.linkFlag}" v-for="(link, index) in row.dynamicLinkFiles" :key="index" @click="linkDowload(link)">{{ link.fileName }}</div>
                  </div>
                </div>
              </transition>
            </template>
          </el-table-column>
          <!-- 没有数据时显示 -->
          <template #empty>
            <i class="iconfont icon-wushuju1 data-empty-icon"></i>
            <h3 class="data-empty">暂无数据</h3>
          </template>
        </el-table>
      </div>
      <Pagination 
        v-show="conditionForm.totalRow > 0" 
        :total="conditionForm.totalRow"
        v-model:page="conditionForm.pageNumber"
        v-model:limit="conditionForm.pageSize"
        @pagination="pageChange" 
      />
    </div>
  </div>
</template>
<script setup>
import Condition from '@/components/common/Condition.vue';
import Pagination from '@/components/common/Pagination';
import JSZip from 'jszip';
import FileSaver from 'file-saver';
import { ref, computed, onActivated } from 'vue';
import { useRouter } from 'vue-router';
import { api } from '@/utils/status';
import { ElMessage, ElMessageBox } from 'element-plus';
import { getModuleLibs } from '@/api/moduleLib.js';
import * as moduleApi from '@/api/module';
import * as fileApi from '@/api/file';

// ============> data
const router = useRouter();
// 搜索条件表单项
const conditionForm = ref({
  flag: false,
  loading: false,
  name: '',
  saveName: '',
  moduleLibId: null,
  moduleLibSelect: [],
  saveModuleLibId: null,
  system: null,
  saveSystem: null,
  status: null,
  saveStatus: null,
  // 页条数
  pageSize: 10,
  // 当前页
  pageNumber: 1,
  // 总条数
  totalRow: 0,
  // 总页数
  totalPage: 0
});
// 模块列表
const moduleLibs = ref([]);
const moduleLibFlats = ref([]);
// 平台列表
const systems = ref(api.common.systems);
const defaults = api.common.defaults;
// 表格的算法数据
const datas = ref([]);


// ============> computed
const getShow = computed(() => {
  return function (v, k, arr, returnKey) {
    let obj = arr.find((item) => item[k] === v);
    let res = obj ? obj[returnKey] : "--";
    return res;
  };
});
const getModuleLibName = computed(() => {
  return function (itemId){
    let names = [];
    function getIdFromArr(id, arr, result){
      let resultItem = arr.find(item => {
        return item.id === id
      });
      if (!resultItem){
        arr = ['返回数据有误'];
        return;
      }
      result.unshift(resultItem.name);
      if (resultItem.parentId !== '0') {
        getIdFromArr(resultItem.parentId, arr, result);
      }
    }
    getIdFromArr(itemId, moduleLibFlats.value, names);
    return names.join(' / ');
  }
});

// ============> methods
function getAllModuleLib(){
  function flatArr(arr){
    let res = [];
    arr.forEach(item => {
      res.push(item);
      if (Array.isArray(item.children) && item.children.length > 0){
        res.push(...flatArr(item.children));
      }
    });
    return res;
  }
  getModuleLibs()
    .then(res => {
      console.log(res)
      if (res && Array.isArray(res) && res.length > 0) {
        moduleLibs.value = res;
        // moduleLibs.value.forEach(item => {
        //   moduleLibFlats.value.push(item);
        //   if (item.children && Array.isArray(item.children)){
        //     moduleLibFlats.value.push(item.children);
        //   }
        // });
        // moduleLibFlats.value = moduleLibFlats.value.flat(Infinity);
        moduleLibFlats.value = flatArr(moduleLibs.value);
      }
    })
}
// 重置上方的搜索条件
function resetCondition(){
  conditionForm.value.name = conditionForm.value.name != conditionForm.value.saveName ? conditionForm.value.saveName : conditionForm.value.name;
  conditionForm.value.moduleLibId = conditionForm.value.moduleLibId != conditionForm.value.saveModuleLibId ? conditionForm.value.saveModuleLibId : conditionForm.value.moduleLibId;
  conditionForm.value.system = conditionForm.value.system != conditionForm.value.saveSystem ? conditionForm.value.saveSystem : conditionForm.value.system;
  conditionForm.value.status = conditionForm.value.status != conditionForm.value.saveStatus ? conditionForm.value.saveStatus : conditionForm.value.status;
}
// 设置上方的搜索条件
function setCondition(){
  conditionForm.value.saveName = conditionForm.value.name;
  conditionForm.value.saveModuleLibId = conditionForm.value.moduleLibId;
  conditionForm.value.saveSystem = conditionForm.value.system;
  conditionForm.value.saveStatus = conditionForm.value.status;
}
// 选择模块库事件
function selectModuleLibs(e){
  if (e && Array.isArray(e) && e.length > 0) {
    conditionForm.value.moduleLibId = e.at(-1);
  } else {
    conditionForm.value.moduleLibId = null;
  }
  getList();
}
// 获取模块库列表
function getList(){
  if (conditionForm.value.flag){
    resetCondition();
    return;
  }
  conditionForm.value.loading = true;
  const { name, moduleLibId, system, status, pageSize, pageNumber} = conditionForm.value;
  moduleApi.getModuleAlgos({ name, moduleLibId, system, status, pageSize, pageNumber })
    .then(res => {
      datas.value = res.records && Array.isArray(res.records) ? res.records : [];
      initDatas();
      setCondition();
      conditionForm.value.pageNumber = +res.pageNumber;
      conditionForm.value.pageSize = +res.pageSize;
      conditionForm.value.totalRow = +res.totalRow;
      conditionForm.value.totalPage = +res.totalPage;
      conditionForm.value.loading= false;
      conditionForm.value.flag = false;
    })
    .catch(err => {
      conditionForm.value.loading = false;
      conditionForm.value.flag = false;
      console.log(err)
      resetCondition();
    })
}
function initDatas(){
  if (Array.isArray(datas.value) && datas.value.length > 0){
    datas.value.forEach(item => {
      item.delFlag = false;
      item.sourceFlag = false;
      item.changeDownload = 0;
      if (Array.isArray(item.linkFiles) && item.linkFiles.length > 1){
        item.linkFiles.forEach(link => {
          link.linkFlag = false;
        })
      }
      if (Array.isArray(item.dynamicLinkFiles) && item.dynamicLinkFiles.length > 1){
        item.dynamicLinkFiles.forEach(link => {
          link.linkFlag = false;
        })
      }
    })
  }
}
// 分页触发事件
function pageChange(e){
  // { page, limit }
  conditionForm.value.pageSize = e.limit;
  conditionForm.value.pageNumber = e.page;
  getList();
}
// 删除
function del(item){
  if (item.delFlag){
    ElMessage.warning('当前正在执行删除，请稍后重试');
    return;
  }
  ElMessageBox.confirm('您是否确认删除该项？', '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消'
  })
    .then(() => {
      item.delFlag = true;
      moduleApi.delModuleAlgo({id: item.id})
        .then(res => {
          ElMessage.success('删除算法成功！');
          item.delFlag = false;
          getList();
        })
        .catch(err => {
          console.log(err)
          item.delFlag = false;
          // let msg = err.msg || err.message || '删除算法失败，请稍后重试或联系管理员';
          // ElMessage.error(msg);
        })
    })
    .catch(() => {})
}
// 切换下载模式
function changeDownload(item, value){
  item.changeDownload = value;
}
function download(item, key, flagKey, warning = '未提供下载结果，请稍后重试或联系管理员!'){
  if (!item[key]){
    ElMessage.warning(warning);
    return;
  }
  item[flagKey] = true;
  fileApi.download({ fileId: item[key]})
    .then(res => {
      if (res && res.fileUrl && res.fileName){
        let { fileName, fileUrl } = res;
        ElMessage.success('下载开始');
        let xhr = new XMLHttpRequest();
        xhr.open('get', fileUrl, true);
        xhr.send();
        xhr.responseType = 'blob';
        xhr.onload = function (){
          if (this.status >= 200 && this.status < 300 || this.status == 304) {
            let blob = new Blob([this.response]),
                a = document.createElement('a'),
                url = window.URL.createObjectURL(blob),
                filename = fileName;
            a.href = url;
            a.download = filename;
            a.click();
            window.URL.revokeObjectURL(url);
            item[flagKey] = false;
          } else {
            ElMessage.error('下载失败，请稍后重试或联系管理员！');
            item[flagKey] = false;
          }
        }
        xhr.onerror = function (e){
          ElMessage.error('下载请求失败，请稍后重试或联系管理员！');
          item[flagKey] = false;
        }
      } else {
        ElMessage.error('未提供下载链接，下载失败，请稍后重试或联系管理员！');
        item[flagKey] = false;
      }
    })
    .catch(err => {
      console.log('下载报错')
      console.log(err)
      // item.downloadFlag = false;
      item[flagKey] = false;
    })
}
function linkDowload(item){
  if (item.linkFlag) {
    ElMessage.warning('当前正在下载，请稍后');
    return;
  }
  if (item.fileUrl){
    item.linkFlag = true;
    ElMessage.success('下载开始');
    let xhr = new XMLHttpRequest();
    xhr.open('get', item.fileUrl, true);
    xhr.send();
    xhr.responseType = 'blob';
    xhr.onload = function (){
      if (this.status >= 200 && this.status < 300 || this.status == 304) {
        let blob = new Blob([this.response]),
            a = document.createElement('a'),
            url = window.URL.createObjectURL(blob),
            filename = item.fileName;
        a.href = url;
        a.download = filename;
        a.click();
        window.URL.revokeObjectURL(url);
        item.linkFlag = false;
      } else {
        ElMessage.error('下载失败，请稍后重试或联系管理员！');
        item.linkFlag = false;
      }
    }
    xhr.onerror = function (e){
      ElMessage.error('下载请求失败，请稍后重试或联系管理员！');
      item.linkFlag = false;
    }
  } else {
    ElMessage.error('未提供下载链接，下载失败，请稍后重试或联系管理员！');
  }
}
// 一键下载
function downloadlinks(item, key){
  ElMessage.success('下载开始');
  const promises = [];
  const zip = new JSZip();
  item[key].forEach(link => {
    const promise = new Promise((resolve, reject) => {
      let xhr = new XMLHttpRequest();
      xhr.open('get', link.fileUrl, true);
      xhr.send();
      xhr.responseType = 'blob';
      xhr.onload = function (){
        if (this.status >= 200 && this.status < 300 || this.status == 304) {
          let blob = new Blob([this.response]);
          zip.file(link.fileName, blob, {binary: true});
          resolve(this.response);
        } else {
          reject(link.fileName);
        }
      }
      xhr.onerror = function (e){
        reject(link.fileName);
      }
    })
    promises.push(promise);
  })
  Promise.all(promises)
    .then(() => {
      // 生成zip 文件
      zip.generateAsync({
        type: 'blob',
        compression: 'DEFLATE',  // STORE: 默认不压缩， DEFLATE：需要压缩
        compressionOptions: {
          level: 9          // 压缩等级 1~9   1 压缩速度最快， 9 最优压缩方式
        }
      })
        .then((res) => {
          ElMessage.success('下载成功');
          FileSaver.saveAs(res, 'linkLibs.zip');
        })
    })
    .catch(() => {
      ElMessage.error('下载失败，请稍后重试或联系管理员');
      console.log('Error!')
    })
}
function linkToCreate(){
  router.push({ name: 'moduleCreate'} );
}
function linkToEdit(item){
  router.push({ name: 'moduleCreate', query: { id: item.id} });
}

onActivated(() => {
  getAllModuleLib();
  getList();
});

</script>
<style lang='scss' scoped>
@import '@/assets/styles/mixin.scss';
.data-add {
  width: 100px;
}
.table-actions {
  display: flex;
  align-items: center;
  justify-content: space-around;
  width: 100%;
  height: 100%;
  .action {
    width: 80px;
  }
}
.table-actions-column {
  width: 100%;
  flex-direction: column;
  .actions-column {
    width: 100%;
    display: flex;
    justify-content: space-around;
  }
}
.green {
  color: var(--color-green);
}
.red {
  color: var(--color-red);
  @include red-text-shadow;
}
.blue {
  color: var(--color-text-hover);
  @include blue-text-shadow;
}
.main-color {
  color: var(--color-main);
  @include main-text-shadow;
}
.condition-item-5 {
  width: 46%;
}
.links {
  height: 120px;
  border: 1px solid var(--color-main);
  // 头部
  .links-top {
    width: 100%;
    height: 20px;
    background-color: var(--color-main);
    line-height: 20px;
    position: relative;
    color: var(--color-white-10);
    font-size: 12px;
    .links-all {
      @include blue-text-shadow;
      cursor: pointer;
    }
    .links-close {
      position: absolute;
      top: 0;
      right: 0;
      width: 20px;
      height: 20px;
      text-align: center;
      font-size: 12px;
      cursor: pointer;
    }
  }
  .links-container {
    width: 100%;
    height: calc(100% - 20px);
    padding: 10px 15px;
    // display: flex;
    // flex-direction: column;
    // justify-content: center;
    align-items: center;
    overflow-y: auto;
    overflow-x: hidden;
    @include scrollBar;
    .links-item {
      width: 100%;
      height: 24px;
      line-height: 24px;
      background-color: var(--color-main);
      color: var(--color-white-10);
      cursor: pointer;
      border-radius: 4px;
      transition: all 0.3 linear;
      margin: 5px 0;
      @include text-overflow-ellipsis;
      &.disabled {
        border: 1px solid var(--color-black-10);
        // background-color: var(--color-white-10);
        background-color: #ccc;
        color: var(--color-black-10);
      }
    }

  }
}
</style>